package com.intelligent.system.auth.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.intelligent.system.auth.dto.*;
import com.intelligent.system.auth.entity.Menu;
import com.intelligent.system.auth.mapper.MenuMapper;
import com.intelligent.system.auth.service.IMenuService;
import com.intelligent.system.common.exception.CustomException;
import com.intelligent.system.common.response.ResponseCode;
import com.intelligent.system.common.response.ResultDO;
import com.intelligent.system.common.utils.SnowflakeIdUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Service
public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements IMenuService {

    @Resource
    private SnowflakeIdUtils idUtils;

    @Override
    public ResultDO<MenuDTO> getMenuById(Long id) {
        try {
            Menu menu = this.getById(id);
            if (menu == null) {
                log.error("未找到ID为 {} 的菜单", id);
                throw new CustomException("菜单不存在", ResponseCode.MENU_NOT_FOUND.getCode());
            }
            MenuDTO menuDTO = new MenuDTO();
            BeanUtils.copyProperties(menu, menuDTO);
            return ResultDO.success(menuDTO);
        } catch (Exception e) {
            log.error("获取菜单失败，ID: {}", id, e);
            throw new CustomException("系统错误", ResponseCode.SYSTEM_ERROR.getCode());
        }
    }

    @Override
    public ResultDO<Page<MenuDTO>> getMenuList(MenuQueryDTO param) {
        try {
            Page<Menu> page = new Page<>(param.getPageNum(), param.getPageSize());
            LambdaQueryWrapper<Menu> wrapper = new LambdaQueryWrapper<>();
            
            // 添加查询条件
            if (StringUtils.hasText(param.getMenuName())) {
                wrapper.like(Menu::getMenuName, param.getMenuName());
            }
            if (StringUtils.hasText(param.getVisible())) {
                wrapper.eq(Menu::getVisible, param.getVisible());
            }
            
            // 执行分页查询
            Page<Menu> resultPage = this.page(page, wrapper);
            
            // 转换为DTO
            Page<MenuDTO> dtoPage = new Page<>();
            BeanUtils.copyProperties(resultPage, dtoPage, "records");
            List<MenuDTO> dtoList = resultPage.getRecords().stream()
                    .map(menu -> {
                        MenuDTO dto = new MenuDTO();
                        BeanUtils.copyProperties(menu, dto);
                        return dto;
                    })
                    .collect(Collectors.toList());
            dtoPage.setRecords(dtoList);
            
            return ResultDO.success(dtoPage);
        } catch (Exception e) {
            log.error("获取菜单列表失败，参数: {}", param, e);
            throw new CustomException("系统错误", ResponseCode.SYSTEM_ERROR.getCode());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultDO<?> addMenu(MenuDTO param) {
        try {
            // 检查菜单名是否已存在
            if (this.checkMenuNameExists(param.getMenuName())) {
                log.error("菜单名已存在: {}", param.getMenuName());
                throw new CustomException("菜单名已存在", ResponseCode.MENU_ALREADY_EXISTS.getCode());
            }

            Menu menu = new Menu();
            BeanUtils.copyProperties(param, menu);
            menu.setMenuId(idUtils.nextId());
            if (this.save(menu)) {
                return ResultDO.success(null);
            }
            throw new CustomException("系统错误", ResponseCode.SYSTEM_ERROR.getCode());
        } catch (CustomException e) {
            throw e;
        } catch (Exception e) {
            log.error("添加菜单失败: {}", param, e);
            throw new CustomException("系统错误", ResponseCode.SYSTEM_ERROR.getCode());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultDO<?> updateMenu(MenuDTO param) {
        try {
            Menu menu = this.getById(param.getMenuId());
            if (menu == null) {
                log.error("未找到ID为 {} 的菜单", param.getMenuId());
                throw new CustomException("菜单不存在", ResponseCode.MENU_NOT_FOUND.getCode());
            }

            // 如果修改了菜单名，需要检查是否已存在
            if (!menu.getMenuName().equals(param.getMenuName()) 
                    && this.checkMenuNameExists(param.getMenuName())) {
                log.error("菜单名已存在: {}", param.getMenuName());
                throw new CustomException("菜单名已存在", ResponseCode.MENU_ALREADY_EXISTS.getCode());
            }

            BeanUtils.copyProperties(param, menu);
            menu.setUpdateTime(LocalDateTime.now());
            if (this.updateById(menu)) {
                return ResultDO.success(null);
            }
            throw new CustomException("系统错误", ResponseCode.SYSTEM_ERROR.getCode());
        } catch (CustomException e) {
            throw e;
        } catch (Exception e) {
            log.error("更新菜单失败: {}", param, e);
            throw new CustomException("系统错误", ResponseCode.SYSTEM_ERROR.getCode());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultDO<?> updateMenuVisible(Long menuId, String visible) {
        try {
            Menu menu = this.getById(menuId);
            if (menu == null) {
                log.error("未找到ID为 {} 的菜单", menuId);
                throw new CustomException("菜单不存在", ResponseCode.MENU_NOT_FOUND.getCode());
            }

            menu.setVisible(visible);
            if (this.updateById(menu)) {
                return ResultDO.success(null);
            }
            throw new CustomException("系统错误", ResponseCode.SYSTEM_ERROR.getCode());
        } catch (CustomException e) {
            throw e;
        } catch (Exception e) {
            log.error("更新菜单可见性失败: menuId={}, visible={}", menuId, visible, e);
            throw new CustomException("系统错误", ResponseCode.SYSTEM_ERROR.getCode());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultDO<?> deleteMenuById(Long menuId) {
        try {
            if (!this.removeById(menuId)) {
                log.error("删除菜单失败: {}", menuId);
                throw new CustomException("系统错误", ResponseCode.SYSTEM_ERROR.getCode());
            }
            return ResultDO.success(null);
        } catch (CustomException e) {
            throw e;
        } catch (Exception e) {
            log.error("删除菜单失败: {}", menuId, e);
            throw new CustomException("系统错误", ResponseCode.SYSTEM_ERROR.getCode());
        }
    }

    private boolean checkMenuNameExists(String menuName) {
        LambdaQueryWrapper<Menu> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Menu::getMenuName, menuName);
        return this.count(wrapper) > 0;
    }
} 